#pragma once

#define DIRECTINPUT_VERSION 0x0800

#define XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE  7849
#define XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE 8689
#define XINPUT_GAMEPAD_TRIGGER_THRESHOLD    30

#pragma comment(lib, "XInput.lib")
#pragma comment(lib, "dinput8.lib")
#pragma comment(lib, "dxguid.lib")

#include <Windows.h>
#include <XInput.h>
#include <dinput.h>
#include "NeroEngine\NInput.h"

#define KEY_COUNT 256



namespace System
{
class GamePad;
class Mouse;
class Keyboard;

class Win32Input : public Engine::NInput
{
public:
	Win32Input(void);
	virtual ~Win32Input(void);
	void Update(float gameTime);
	virtual bool Initialize();
	virtual void Deinitialize();

	virtual void HandleKeyDown(unsigned wParam, long lParam);
	virtual void HandleKeyUp(unsigned wParam, long lParam);

	virtual bool IsKeyDown(int keyValue);

	Mouse* GetMouse();

private:
	GamePad* mGamePads;
	IDirectInput8* mDirectInput;
	Keyboard* mKeyboard;
	Mouse* mMouse;
};

class GamePad
{
	friend Win32Input;
public:
    GamePad();
	~GamePad();
    XINPUT_STATE GetState();
    bool IsConnected();
    void Vibrate(int leftVal = 0, int rightVal = 0);
	void Update(float gameTime);
private:
    XINPUT_STATE mCurrentControllerState;
	XINPUT_STATE mPreviousControllerState;
    int mControllerNumber;
};

class Keyboard
{
	friend Win32Input;
public:
	Keyboard();
	~Keyboard();
	bool Initialize(IDirectInput8* device, HWND winHandle);
	void Update(float gameTime);
	IDirectInputDevice8* GetDevice();
private:
	IDirectInputDevice8* mKeyboardDevice;
	bool mKeys[KEY_COUNT];
};

class Mouse
{
	friend Win32Input;
public:
	enum MouseButtons
	{
		LEFT,		//!< Value for left button
		RIGHT,		//!< Value for right button
		MIDDLE,		//!< Value for middle button
		BACK,		//!< Value for back button
		FORWARD		//!< Value for forward button
	};
public:
	Mouse();
	~Mouse();
	void Initialize(IDirectInput8* device, HWND winHandle);
	void Update(float gameTime);
	IDirectInputDevice8* GetDevice();

	long DeltaX() const;
	long DeltaY() const;
private:
	IDirectInputDevice8* mMouseDevice;
	DIMOUSESTATE mCurrentStateInfo;
	DIMOUSESTATE mPrevStateInfo;
	POINT mPosition;
	long mDeltaX, mDeltaY;
};

enum KEY
{
	Key_0 = 48,
	Key_1,
	Key_2,
	Key_3,
	Key_4,
	Key_5,
	Key_6,
	Key_7,
	Key_8,
	Key_9 = 57,

	KEY_A = 65,
	KEY_B,
	KEY_C,
	KEY_D,
	KEY_E,
	KEY_F,
	KEY_G,
	KEY_H,
	KEY_I,
	KEY_K,
	KEY_L,
	KEY_M,
	KEY_N,
	KEY_O,
	KEY_P,
	KEY_Q,
	KEY_R,
	KEY_S,
	KEY_T,
	KEY_U,
	KEY_V,
	KEY_W,
	KEY_X,
	KEY_Y,
	KEY_Z = 90,
};
}